#include <stdio.h>
#include <stdlib.h>

#include "SDL/SDL.h"

#include "constantes_et_macros.h"

#include "base_donnees.h"
#include "projectiles.h"
#include "cases.h"
#include "parsing.h"
#include "manipulation_ennemis.h"
#include "affichage.h"






struct base_donnees* creer_base_donnees(void)
{
    struct base_donnees* donnees;

    if(!(donnees = (struct base_donnees*)malloc(sizeof(struct base_donnees))))
        exit(EXIT_MALLOC);
    donnees->ecran = NULL;
    donnees->sprites_ennemis = NULL;
    donnees->sprites_joueur = NULL;
    donnees->sprites_projectiles = NULL;
    donnees->tuiles = NULL;

    return donnees;
}



void remplir_base_donnees(struct base_donnees* donnees)
{
    lire_fichier_ennemis(donnees);
    lire_fichier_objets(donnees);
    lire_fichier_projectiles(donnees);
    lire_fichier_niveaux(donnees);
    lire_fichier_dependances(donnees);
    lire_fichier_magasin(donnees);
    lire_fichier_quetes(donnees);
    lire_fichier_cartes(donnees);
    donnees->ecran = creer_ecran(DIM_ECRAN_X, DIM_ECRAN_Y);
    donnees->sprites_ennemis = charger_image("donnees/images/sprites_ennemis.bmp");
    donnees->sprites_joueur = charger_image("donnees/images/sprites_joueur.bmp");
    donnees->sprites_projectiles = charger_image("donnees/images/sprites_projectiles.bmp");
    donnees->tuiles = charger_image("donnees/images/tuiles.bmp");
    donnees->barre_vie_joueur = charger_image("donnees/images/barre_vie_joueur.bmp");
    donnees->barre_vie_ennemis = charger_image("donnees/images/barre_vie_ennemis.bmp");
    donnees->barre_charge = charger_image("donnees/images/barre_charge.bmp");
    donnees->zones_carte_region = charger_image("donnees/images/zones_carte_region.bmp");
    donnees->font_utilisee = ouvrir_font("donnees/fonts/font_defaut.ttf",
                                         TAILLE_FONT_DEFAUT, FAUX);
}


void detruire_base_donnees(struct base_donnees* donnees)
{
    detruire_tab_dyn_description_ennemis(&donnees->tab_ennemis);
    detruire_tab_dyn_description_objets(&donnees->tab_objets);
    detruire_tab_dyn_description_projectiles(&donnees->tab_projectiles);
    detruire_tab_dependances(&donnees->dependances);
    detruire_tab_dyn_id(&donnees->objets_en_vente);
    detruire_tab_dyn_quetes(&donnees->tab_quetes);
    detruire_tab_dyn_regions(&donnees->tab_regions);
    detruire_surface(donnees->ecran);
    detruire_surface(donnees->sprites_ennemis);
    detruire_surface(donnees->sprites_joueur);
    detruire_surface(donnees->sprites_projectiles);
    detruire_surface(donnees->tuiles);
    detruire_surface(donnees->barre_vie_joueur);
    detruire_surface(donnees->barre_vie_ennemis);
    detruire_surface(donnees->barre_charge);
    detruire_surface(donnees->zones_carte_region);
    fermer_font(donnees->font_utilisee);
    free(donnees);
}



void charger_font_titres(struct base_donnees* donnees)
{
    fermer_font(donnees->font_utilisee);
    donnees->font_utilisee = ouvrir_font("donnees/fonts/font_titres.ttf",
                                         TAILLE_FONT_TITRES, VRAI);
}



void charger_font_defaut(struct base_donnees* donnees)
{
    fermer_font(donnees->font_utilisee);
    donnees->font_utilisee = ouvrir_font("donnees/fonts/font_defaut.ttf",
                                         TAILLE_FONT_DEFAUT, VRAI);
}





/* =============== accesseurs pour descriptions d'ennemis ================== */



unsigned int get_loc_sprites(const struct base_donnees* donnees, const struct ennemi* enn)
{
    return donnees->tab_ennemis.tab[enn->id].localisation_sprites;
}



unsigned int get_pv_max(const struct base_donnees* donnees, const struct ennemi* enn)
{
    return donnees->tab_ennemis.tab[enn->id].pv;
}



unsigned int get_vit_depl(const struct base_donnees* donnees, const struct ennemi* enn)
{
    return donnees->tab_ennemis.tab[enn->id].vitesse_deplacement;
}



unsigned int get_puissance(const struct base_donnees* donnees, const struct ennemi* enn)
{
    return donnees->tab_ennemis.tab[enn->id].puissance;
}



unsigned int get_vit_charge(const struct base_donnees* donnees, const struct ennemi* enn)
{
    return donnees->tab_ennemis.tab[enn->id].vitesse_charge;
}



char* get_nom_ennemi(const struct base_donnees* donnees, const struct ennemi* enn)
{
    return donnees->tab_ennemis.tab[enn->id].nom;
}



unsigned char get_id_projectile(const struct base_donnees* donnees, const struct ennemi* enn)
{
    return donnees->tab_ennemis.tab[enn->id].id_projectile;
}



unsigned char get_taille(const struct base_donnees* donnees, const struct ennemi* enn)
{
    return donnees->tab_ennemis.tab[enn->id].taille;
}



char get_type_attaque(const struct base_donnees* donnees, const struct ennemi* enn)
{
    return donnees->tab_ennemis.tab[enn->id].type_attaque;
}



char get_stats_vol(const struct base_donnees* donnees, const struct ennemi* enn)
{
    return donnees->tab_ennemis.tab[enn->id].volant;
}



unsigned int get_pv_max_par_id(const struct base_donnees* donnees, const unsigned int id_ennemi)
{
    return donnees->tab_ennemis.tab[id_ennemi].pv;
}



unsigned int get_vit_depl_par_id(const struct base_donnees* donnees, const unsigned int id_ennemi)
{
    return donnees->tab_ennemis.tab[id_ennemi].vitesse_deplacement;
}



unsigned int get_puissance_par_id(const struct base_donnees* donnees, const unsigned int id_ennemi)
{
    return donnees->tab_ennemis.tab[id_ennemi].puissance;
}



unsigned int get_vit_charge_par_id(const struct base_donnees* donnees, const unsigned int id_ennemi)
{
    return donnees->tab_ennemis.tab[id_ennemi].vitesse_charge;
}



char* get_nom_ennemi_par_id(const struct base_donnees* donnees, const unsigned int id_ennemi)
{
    return donnees->tab_ennemis.tab[id_ennemi].nom;
}



void get_drops_par_id(const struct base_donnees* donnees, struct tab_dyn_id** objets,
                      struct tab_dyn_id** probas, const unsigned int id_ennemi)
{
    *objets = &donnees->tab_ennemis.tab[id_ennemi].drops;
    *probas = &donnees->tab_ennemis.tab[id_ennemi].probas;
}



/* =============== accesseurs pour descriptions d'objets =================== */

char* get_nom_objet(const struct base_donnees* donnees, const unsigned int id)
{
    if(id == VIDE)
        return NULL;
    else
        return donnees->tab_objets.tab[id].nom;
}



char get_type_objet(const struct base_donnees* donnees, const unsigned int id)
{
    if(id == VIDE)
        return 0;
    else
        return donnees->tab_objets.tab[id].type;
}



unsigned int get_pv_objet(const struct base_donnees* donnees, const unsigned int id)
{
    if(id == VIDE)
        return 0;
    else
        return donnees->tab_objets.tab[id].pv;
}



unsigned int get_vitesse_deplacement_objet(const struct base_donnees* donnees, const unsigned int id)
{
    if(id == VIDE)
        return 0;
    else
        return donnees->tab_objets.tab[id].vitesse_deplacement;
}



unsigned int get_puissance_objet(const struct base_donnees* donnees, const unsigned int id)
{
    if(id == VIDE)
        return 0;
    else
        return donnees->tab_objets.tab[id].puissance;
}



unsigned int get_vitesse_charge_objet(const struct base_donnees* donnees, const unsigned int id)
{
    if(id == VIDE)
        return 0;
    else
        return donnees->tab_objets.tab[id].vitesse_charge;
}



unsigned int get_prix_vente(const struct base_donnees* donnees, const unsigned int id)
{
    if(id == VIDE)
        return 0;
    else
        return donnees->tab_objets.tab[id].prix_vente;
}



unsigned int get_prix_achat(const struct base_donnees* donnees, const unsigned int id)
{
    return 2 * get_prix_vente(donnees, id);
}



unsigned char get_id_projectile_objet(const struct base_donnees* donnees, const unsigned int id)
{
    if(id == VIDE)
        return 0;
    else
        return donnees->tab_objets.tab[id].id_projectile;
}



/* =============== accesseurs pour descriptions de projectiles ================== */



unsigned int get_loc_sprites_projectile(const struct base_donnees* donnees, const struct projectile* proj)
{
    return donnees->tab_projectiles.tab[proj->id].localisation_sprites;
}



unsigned int get_vitesse_deplacement_projectile(const struct base_donnees* donnees, const struct projectile* proj)
{
    return donnees->tab_projectiles.tab[proj->id].vitesse_deplacement;
}



unsigned int get_vitesse_deplacement_projectile_par_id(const struct base_donnees* donnees,
                                                       const unsigned char id)
{
    return donnees->tab_projectiles.tab[id].vitesse_deplacement;
}



unsigned char  get_taille_projectile(const struct base_donnees* donnees, const struct projectile* proj)
{
    return donnees->tab_projectiles.tab[proj->id].taille;
}


unsigned char  get_taille_projectile_par_id(const struct base_donnees* donnees, const unsigned char id)
{
    return donnees->tab_projectiles.tab[id].taille;
}


/* =============== experience ============== */

unsigned char calculer_niveau(const unsigned int experience,
                              const struct base_donnees* donnees)
{
    unsigned char niveau;

    niveau = 1;
    while(niveau < 99 && experience >= donnees->paliers_xp[niveau - 1])
        niveau++;

    return niveau;
}


unsigned int donner_palier_suivant(const unsigned char niveau,
                                   const struct base_donnees* donnees)
{
    return donnees->paliers_xp[niveau - 1];
}


/* =============== quetes ============== */

unsigned int get_recompense(const struct base_donnees* donnees,
                            const unsigned int id_quete)
{
    return donnees->tab_quetes.tab[id_quete].recompense;
}



struct objet* get_objets_necessaires(const struct base_donnees* donnees,
                                     const unsigned int id_quete)
{
    return donnees->tab_quetes.tab[id_quete].objets_necessaires.prem;
}


/* =============== regions =============== */

const char* get_nom_region(const struct base_donnees* donnees,
                           const unsigned int id_region)
{
    int i;

    for(i = 0;  i < donnees->tab_regions.nb_elements;  i++)
    {
        if(donnees->tab_regions.tab[i].id == id_region)
            return donnees->tab_regions.tab[i].nom;
    }
    printf("Erreur dans get_nom_region (id = %u)\n", id_region);
    exit(EXIT_FAILURE);
}



void get_coord_region(const struct base_donnees* donnees,
                      const unsigned int id_region,
                      unsigned int* x,
                      unsigned int* y)
{
    int i;

    for(i = 0;  i < donnees->tab_regions.nb_elements;  i++)
    {
        if(donnees->tab_regions.tab[i].id == id_region)
        {
            *x = donnees->tab_regions.tab[i].coord_x;
            *y = donnees->tab_regions.tab[i].coord_y;
            return;
        }
    }
    printf("Erreur dans get_coord_region (id = %u)\n", id_region);
    exit(EXIT_FAILURE);
}



const char* get_tout_region(const struct base_donnees* donnees,
                            const unsigned int id_region,
                            unsigned int* x,
                            unsigned int* y)
{
    int i;
    struct region* p_region;

    for(i = 0;  i < donnees->tab_regions.nb_elements;  i++)
    {
        if(donnees->tab_regions.tab[i].id == id_region)
        {
            p_region = donnees->tab_regions.tab + i;
            *x = p_region->coord_x;
            *y = p_region->coord_y;
            return p_region->nom;
        }
    }
    printf("Erreur dans get_tout_region (id = %u)\n", id_region);
    exit(EXIT_FAILURE);
}



